﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Threading;
using System.Net;
using System.ComponentModel;
using System.IO;
using System.Windows.Threading;
using System.Collections.ObjectModel;

namespace SAF.Framework.Controls.Upgrade
{
    /// <summary>
    /// UpgradeWizard.xaml 的交互逻辑
    /// </summary>
    public partial class UpgradeWizard : Window
    {
        /// <summary>
        /// 每个文件下载完成的信息号量
        /// </summary>
        private ManualResetEvent evtPerDonwloadFinished = null;
        private WebClient clientDownload = null;
        /// <summary>
        /// 是否全部下载完成
        /// </summary>
        private bool m_DownloadIsFinished = true;
        /// <summary>
        /// 用于下载的线程
        /// </summary>
        private BackgroundWorker m_DownLoadWorker = new BackgroundWorker();
        /// <summary>
        /// 旧文件的后缀名
        /// </summary>
        private string m_OldFileExtension = ".tauof";

        private List<DownloadFile> m_DownloadList = new List<DownloadFile>();
        /// <summary>
        /// 下载列表
        /// </summary>
        internal List<DownloadFile> DownloadFileList
        {
            set
            {
                m_DownloadList = value;
                this.dgDownloadList.ItemsSource = this.m_DownloadList;
            }
        }
        /// <summary>
        /// 是否是正在下载状态
        /// </summary>
        private void IsDownloading(bool downloading)
        {
            if (downloading)
            {
                this.pbDownloadProgress.Visibility = Visibility.Visible;
                this.txtCurrentFile.Visibility = Visibility.Visible;
                this.btnUpdate.IsEnabled = false;
                this.btnExit.IsEnabled = false;
                Grid.SetRowSpan(this.dgDownloadList, 1);
            }
            else
            {
                this.pbDownloadProgress.Visibility = Visibility.Hidden;
                this.txtCurrentFile.Visibility = Visibility.Hidden;
                this.btnUpdate.IsEnabled = true;
                this.btnExit.IsEnabled = true;
                Grid.SetRowSpan(this.dgDownloadList, 3);
            }
        }
        /// <summary>
        /// 原有旧版本文件存放文件夹
        /// </summary>
        private string OldFilePath
        {
            get
            {
                return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ".upgrade");
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public UpgradeWizard()
        {
            InitializeComponent();
            this.IsDownloading(false);

            m_DownLoadWorker.DoWork += new DoWorkEventHandler(m_DownLoadWorker_DoWork);
            m_DownLoadWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_DownLoadWorker_RunWorkerCompleted);
        }
        /// <summary>
        /// 全部下载完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void m_DownLoadWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            m_DownloadIsFinished = true;

            this.btnUpdate.IsEnabled = false;
            this.IsDownloading(false);
            Helper.RestartApplication();
        }
        /// <summary>
        /// 创建升级目录，检查升级目录是否存在，如存在删除重建
        /// </summary>
        private void CreateUpgradeDirectory()
        {
            if (Directory.Exists(OldFilePath))
            {
                Directory.Delete(OldFilePath, true);
            }
            Directory.CreateDirectory(OldFilePath);
            File.SetAttributes(OldFilePath, FileAttributes.Hidden);
        }
        /// <summary>
        /// 下载操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUpdate_Click(object sender, RoutedEventArgs e)
        {
            if (this.m_DownloadList.Count <= 0)
            {
                MessageBox.Show(Properties.Resources.NoFileNeedUpgrade,
                    this.Title, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            m_DownloadIsFinished = false;
            //创建升级目录
            CreateUpgradeDirectory();
            this.IsDownloading(true);

            m_DownLoadWorker.RunWorkerAsync();
        }
        /// <summary>
        /// 开始下载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void m_DownLoadWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            evtPerDonwloadFinished = new ManualResetEvent(false);
            for (int i = 0; i < m_DownloadList.Count; i++)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                DownloadFile file = m_DownloadList[i];
                //显示正在下载的文件
                this.txtCurrentFile.Dispatcher.Invoke(new Action<DownloadFile>(
                    (f) =>
                    {
                        ShowCurrentFileDownloadProgress(f.FileName);
                        f.State = Properties.Resources.FileUpgrading;
                    }), DispatcherPriority.DataBind, file);

                this.pbDownloadProgress.Dispatcher.Invoke(new Action<double, double>(SetProcessBar), DispatcherPriority.DataBind, 0d, (double)file.Size);
                //下载
                clientDownload = new WebClient();
                clientDownload.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged);
                clientDownload.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadFileCompleted);

                evtPerDonwloadFinished.Reset();
                clientDownload.DownloadFileAsync(new Uri(file.Path), System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileName + ".tmp"), file);
                //等待下载完成
                evtPerDonwloadFinished.WaitOne();
                clientDownload.Dispose();
                clientDownload = null;
            }
        }
        /// <summary>
        /// 下载进度步变化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            this.pbDownloadProgress.Dispatcher.Invoke(new Action<double, double>(SetProcessBar), DispatcherPriority.DataBind, (double)e.BytesReceived, 0d);
            this.txtCurrentFile.Dispatcher.Invoke(new Action<string>(ShowCurrentFileDownloadProgress), DispatcherPriority.DataBind, ((DownloadFile)e.UserState).FileName);
        }
        /// <summary>
        /// 单个文件下载完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            DownloadFile file = e.UserState as DownloadFile;
            //替换现有文件
            string filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file.FileName);
            string oldFileName = System.IO.Path.Combine(OldFilePath, file.FileName + this.m_OldFileExtension);
            if (File.Exists(filePath))
            {
                if (File.Exists(oldFileName))
                    File.Delete(oldFileName);
                File.Move(filePath, oldFileName);
            }
            File.Move(filePath + ".tmp", filePath);
            file.State = Properties.Resources.FileUpgradeComplete;
            //继续下载其它文件
            evtPerDonwloadFinished.Set();
        }
        /// <summary>
        /// 显示当前正在下载的文件
        /// </summary>
        /// <param name="file"></param>
        private void ShowCurrentFileDownloadProgress(string fileName)
        {
            float process = (float)(this.pbDownloadProgress.Value / this.pbDownloadProgress.Maximum * 100);
            this.txtCurrentFile.Text = Properties.Resources.FileCurrentDownload +
                fileName + " ... (" + process.ToString("0.#") + " %)";
        }
        /// <summary>
        /// 设置进度条
        /// </summary>
        /// <param name="current"></param>
        /// <param name="maxValue"></param>
        private void SetProcessBar(double current, double maxValue)
        {
            if (maxValue > 0)
            {
                this.pbDownloadProgress.Maximum = maxValue;
            }
            if (current > this.pbDownloadProgress.Maximum)
            {
                current = this.pbDownloadProgress.Maximum;
            }
            this.pbDownloadProgress.Value = current;
        }
        /// <summary>
        /// 正在下载时，不允许关闭窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closing(object sender, CancelEventArgs e)
        {
            if (!m_DownloadIsFinished)
            {
                e.Cancel = true;
            }
        }
    }
}
